#pragma once

#include<iostream>
#include<vector>
#include<unistd.h>
#include<pthread.h>
#include<semaphore.h>

template <typename T>

class RingQueue{

    public:
    RingQueue(int _cp):cp(_cp),
                       qe(_cp),
                       consumer_number(0),
                       procductor_number(0)
    {
        pthread_mutex_init(&consumer,nullptr);
        pthread_mutex_init(&consumer,nullptr);
        
        sem_init(&room_sem,0,_cp);
        sem_init(&data_sem,0,0);

    }

    void Enque(T& in)
    {
        sem_wait(&room_sem);
        pthread_mutex_lock(&procductor);
        qe[procductor_number++]=in;
        procductor_number%=cp;
        pthread_mutex_unlock(&procductor);
        sem_post(&data_sem);

    }
    void Pop(T* out)
    {
        sem_wait(&data_sem);
        pthread_mutex_lock(&consumer);
        *out=qe[consumer_number++];
        consumer_number%=cp;
        pthread_mutex_unlock(&consumer);
        sem_post(&room_sem);
    }
    private:

    std::vector<T> qe;
    int cp;

    int consumer_number;
    int procductor_number;

    pthread_mutex_t consumer;
    pthread_mutex_t procductor;

    sem_t room_sem;
    sem_t data_sem;
    
};